package com.jubao.ejb.dao.impl;

import java.util.List;

import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.interceptor.Interceptors;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import org.apache.log4j.Logger;
import org.jboss.ejb3.annotation.LocalBinding;
import org.jboss.ejb3.annotation.RemoteBinding;

import com.jubao.ejb.dao.GeneRelationDaoLocal;
import com.jubao.ejb.dao.GeneRelationDaoRemote;
import com.jubao.ejb.dao.interceptor.TracingInterceptor;
import com.jubao.ejb.dao.util.DaoConstant;
import com.jubao.ejb.dao.util.DaoUtil;
import com.jubao.ejb.entity.Brand;
import com.jubao.ejb.entity.Category;
import com.jubao.ejb.entity.GeneEntity;
import com.jubao.ejb.entity.GeneRelation;
import com.jubao.ejb.entity.Product;
import com.jubao.ejb.entity.Store;
import com.jubao.ejb.entity.User;
import com.jubao.ejb.entity.Website;

/**
 * @author conan
 * 
 */
@Stateless
@Local( { GeneRelationDaoLocal.class })
@LocalBinding(jndiBinding = DaoConstant.GeneRelationDaoLocalJndiName)
@Remote( { GeneRelationDaoRemote.class })
@RemoteBinding(jndiBinding = DaoConstant.GeneRelationDaoRemoteJndiName)
@Interceptors( { TracingInterceptor.class })
public class GeneRelationDaoImpl implements GeneRelationDaoLocal, GeneRelationDaoRemote {

	/**
	 * 
	 */
	private static final long serialVersionUID = 5153699122990640685L;

	static Logger logger = Logger.getLogger(GeneRelationDaoImpl.class);

	@PersistenceContext(unitName = "default")
	protected EntityManager em;

	/* (non-Javadoc)
	 * @see com.jubao.ejb.dao.GeneRelationDao#save(com.jubao.ejb.entity.GeneRelation)
	 */
	public GeneRelation save(GeneRelation relation) {
		return em.merge(relation);
	}

	/* (non-Javadoc)
	 * @see com.jubao.ejb.dao.GeneRelationDao#findGeneRelationBySysId(long)
	 */
	public GeneRelation find(long sysId) {
		return em.find(GeneRelation.class, sysId);
	}

	/* (non-Javadoc)
	 * @see com.jubao.ejb.dao.GeneRelationDao#find(long, int, long)
	 */
	@SuppressWarnings("unchecked")
	public GeneRelation find(long entitySysId, int relationId, long entity2SysId) {
		List<GeneRelation> grs = this.getRelationList(entitySysId, relationId, entity2SysId, 0, 1);
		GeneRelation result = null;
		if (grs != null && grs.size() > 0) {
			result = grs.get(0);
		}
		return result;
	}

	@SuppressWarnings("unchecked")
	public List<GeneRelation> getRelationList( long entitySysId, int relationId, 
			long entity2SysId, int pgno, int pgsize) {
		Query q = this.composeGetRelationQuery( entitySysId, relationId,  entity2SysId, true);
		//.setHint("org.hibernate.cacheRegion",	"/entity/Category/RelatedCategory/List")
		List result = DaoUtil.getResultList(q, pgno, pgsize);
		return result;

	}

	public long getRelationCount( long entitySysId, int relationId, 
			long entity2SysId) {
		Query q = this.composeGetRelationQuery(entitySysId, relationId, entity2SysId, false);
		Long result = (Long) q.getSingleResult();
		return result;
	}

	private Query composeGetRelationQuery( long entitySysId, int relationId, 
			long entity2SysId, boolean isGetList) {
		String ent = isGetList ? "gr" : "count(gr)";

		String eql = "select " + ent + " from  GeneRelation gr";
		String whereand = "";
		if (entitySysId > -1) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  gr.entity.sysId=:entitySysId ";
		}
		if (relationId > -1) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  gr.relationId=:relationId ";
		}
		if (entity2SysId > -1) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  gr.entity2.sysId=:entity2SysId ";
		}
		logger.info("eql=[" + eql + "]");

		Query q = em.createQuery(eql);
		if (entitySysId > -1) {
			q.setParameter("entitySysId", entitySysId);
		}
		if (relationId > -1) {
			q.setParameter("relationId", relationId);
		}
		if (entity2SysId > -1) {
			q.setParameter("entity2SysId", entity2SysId);
		}
		return q;
	}

	/* (non-Javadoc)
	 * @see com.jubao.ejb.dao.GeneRelationDao#getEntityCount(int, long, int, long, int)
	 */
	public long getEntityCount(String entityName, int relationId1, long entity1SysId, int relationId2,
			long entity2SysId, int relationId3, long entity3SysId, int actionType) {
		Query q = this.composeGetEntityQuery(relationId1, entity1SysId, relationId2, entity2SysId, relationId3,
				entity3SysId, actionType, entityName, false);
		Long result = (Long) q.getSingleResult();
		return result;
	}

	/* (non-Javadoc)
	 * @see com.jubao.ejb.dao.GeneRelationDao#getEntityList(int, long, int, long, int, int, int)
	 */
	public List<GeneEntity> getEntityList(String entityName, int relationId1, long entity1SysId, int relationId2,
			long entity2SysId, int relationId3, long entity3SysId, int actionType, int pgno, int pgsize) {
		Query q = this.composeGetEntityQuery(relationId1, entity1SysId, relationId2, entity2SysId, relationId3,
				entity3SysId, actionType, entityName, true);
		//.setHint("org.hibernate.cacheRegion",	"/entity/Category/RelatedCategory/List")
		List result = DaoUtil.getResultList(q, pgno, pgsize);
		return result;
	}

	private Query composeGetEntityQuery(int relationId1, long entity1SysId, int relationId2, long entity2SysId,
			int relationId3, long entity3SysId, int actionType, String entityName, boolean isGetList) {
		if ((actionType == DaoConstant.GetEntity_XE1_XE2_XE3)
				&& entityName != null
				&& (entityName.equals(Brand.class.getName()) || entityName.equals(Product.class.getName())
						|| entityName.equals(Store.class.getName()) || entityName.equals(Website.class.getName()) || entityName.equals(Category.class.getName())
						|| entityName.equals(User.class.getName()) || entityName.equals(GeneRelation.class.getName()))) {

			String ent = isGetList ? "entx" : "count(entx)";
			String eql = "SELECT " + ent + " FROM " + entityName + " entx ";
			if (relationId1 > -1 || entity1SysId > -1) {
				eql += ", GeneRelation gr1 ";
			}
			if (relationId2 > -1 || entity2SysId > -1) {
				eql += ", GeneRelation gr2 ";
			}
			if (relationId3 > -1 || entity3SysId > -1) {
				eql += ", GeneRelation gr3 ";
			}

			String whereand = "";
			if (actionType == DaoConstant.GetEntity_XE1_XE2_XE3) {
				if (relationId1 > -1 || entity1SysId > -1) {
					whereand = DaoUtil.getWhereOrAndStr(whereand);
					eql += whereand + "  entx=gr1.entity ";
					if (relationId1 > -1) {
						whereand = DaoUtil.getWhereOrAndStr(whereand);
						eql += whereand + "  gr1.relationId=:relationId1 ";
					}
					if (entity1SysId > -1) {
						whereand = DaoUtil.getWhereOrAndStr(whereand);
						eql += whereand + "  gr1.entity2.sysId=:entity1SysId ";
					}
				}
				if (relationId2 > -1 || entity2SysId > -1) {
					whereand = DaoUtil.getWhereOrAndStr(whereand);
					eql += whereand + "  entx=gr2.entity ";
					if (relationId2 > -1) {
						whereand = DaoUtil.getWhereOrAndStr(whereand);
						eql += whereand + "  gr2.relationId=:relationId2 ";
					}
					if (entity2SysId > -1) {
						whereand = DaoUtil.getWhereOrAndStr(whereand);
						eql += whereand + "  gr2.entity2.sysId=:entity2SysId ";
					}
				}
				if (relationId3 > -1 || entity3SysId > -1) {
					whereand = DaoUtil.getWhereOrAndStr(whereand);
					eql += whereand + "  entx=gr3.entity ";
					if (relationId3 > -1) {
						whereand = DaoUtil.getWhereOrAndStr(whereand);
						eql += whereand + "  gr3.relationId=:relationId3 ";
					}
					if (entity3SysId > -1) {
						whereand = DaoUtil.getWhereOrAndStr(whereand);
						eql += whereand + "  gr3.entity2.sysId=:entity3SysId ";
					}
				}
			}

			logger.info("eql=[" + eql + "] relationId1=" + relationId1 + " entity1SysId=" + entity1SysId
					+ " relationId2=" + relationId2 + " entity2SysId=" + entity2SysId + " relationId3=" + relationId3
					+ " entity3SysId=" + entity3SysId);

			Query q = em.createQuery(eql);
			if (relationId1 > -1) {
				q.setParameter("relationId1", relationId1);
			}
			if (entity1SysId > -1) {
				q.setParameter("entity1SysId", entity1SysId);
			}
			if (relationId2 > -1) {
				q.setParameter("relationId2", relationId2);
			}
			if (entity2SysId > -1) {
				q.setParameter("entity2SysId", entity2SysId);
			}
			if (relationId3 > -1) {
				q.setParameter("relationId3", relationId3);
			}
			if (entity3SysId > -1) {
				q.setParameter("entity3SysId", entity3SysId);
			}
			return q;
		}
		return null;
	}

	public List<GeneEntity> getEntityList(String entityName, int relationId1, long entity1SysId, int relationId2,
			long entity2SysId, int pgno, int pgsize) {
		return this.getEntityList(entityName, relationId1, entity1SysId, relationId2, entity2SysId, -1, -1,
				DaoConstant.GetEntity_XE1_XE2_XE3, pgno, pgsize);
	}

	public long getEntityCount(String entityName, int relationId1, long entity1SysId, int relationId2, long entity2SysId) {
		return this.getEntityCount(entityName, relationId1, entity1SysId, relationId2, entity2SysId, -1, -1,
				DaoConstant.GetEntity_XE1_XE2_XE3);
	}

	public long getEntityCount(String entityName, int relationId1, long entity1SysId) {
		return this.getEntityCount(entityName, relationId1, entity1SysId, -1, -1);
	}

	public List<GeneEntity> getEntityList(String entityName, int relationId1, long entity1SysId, int pgno, int pgsize) {
		return this.getEntityList(entityName, relationId1, entity1SysId, -1, -1, pgno, pgsize);
	}

	public void remove(GeneRelation relation) {
		em.remove(relation);
	}

	public long getEntity2Count(long entity1SysId, int relationId1, long entity2SysId,String entity2Name) {
		Query q = this.composeGetEntity2Query( entity1SysId, relationId1, entity2SysId, entity2Name, false);
		Long result = (Long) q.getSingleResult();
		return result;
	}

	public List<GeneEntity> getEntity2List(long entity1SysId, int relationId1, long entity2SysId,String entity2Name,  int pgno, int pgsize) {
		Query q = this.composeGetEntity2Query( entity1SysId, relationId1,entity2SysId,  entity2Name, true);
		//.setHint("org.hibernate.cacheRegion",	"/entity/Category/RelatedCategory/List")
		List result = DaoUtil.getResultList(q, pgno, pgsize);
		return result;
	}
	
	private Query composeGetEntity2Query( long entity1SysId, int relationId1, 
			long entity2SysId,String entity2Name, boolean isGetList) {
		String ent = isGetList ? "entx" : "count(entx)";

		String eql = "select " + ent + " from  GeneRelation gr, "+entity2Name+" entx ";
		String whereand = "";
		if (entity1SysId > -1) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  gr.entity.sysId=:entity1SysId ";
		}
		if (relationId1 > -1) {
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  gr.relationId=:relationId1 ";
		}
		if(entity2SysId>-1){
			whereand = DaoUtil.getWhereOrAndStr(whereand);
			eql += whereand + "  gr.entity2.sysId=:entity2SysId ";
			
		}
		whereand = DaoUtil.getWhereOrAndStr(whereand);
		eql += whereand + "  gr.entity2=entx ";
		
		logger.info("eql=[" + eql + "]");

		Query q = em.createQuery(eql);
		if (entity1SysId > -1) {
			q.setParameter("entity1SysId", entity1SysId);
		}
		if (relationId1 > -1) {
			q.setParameter("relationId1", relationId1);
		}
		if (entity2SysId > -1) {
			q.setParameter("entity2SysId", entity2SysId);
		}
		return q;
	}
}
